package com.example.flex.service.impl.generator;

import cn.hutool.core.collection.CollUtil;
import com.example.flex.common.exception.BusinessException;
import com.example.flex.domain.generator.ColumnEntity;
import com.example.flex.domain.generator.TableEntity;
import com.example.flex.service.generator.CodeService;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.List;

import static com.example.flex.constant.StaticConstant.DEFAULT_ENCODING;
import static com.example.flex.constant.StaticConstant.TEMPLATES_PATH;

/**
 * @Author: 不是菜鸡爱编程
 * @Date: 2023/10/25/22:01
 * @Description:
 */
@Slf4j
@Service
public class CodeServiceImpl implements CodeService {
    Configuration configuration = null;

    {
        configuration = new Configuration(Configuration.VERSION_2_3_31);
        configuration.setTemplateLoader(new ClassTemplateLoader(CodeServiceImpl.class, TEMPLATES_PATH));
        configuration.setDefaultEncoding(DEFAULT_ENCODING);
    }

    @Override
    public boolean generateCode(List<TableEntity> tableList, String generatorCodePath) {
        try {
            Template modelTemplate = configuration.getTemplate("Entity.java.ftl");
            Template mapperJavaTemplate = configuration.getTemplate("Mapper.java.ftl");
            Template mapperXmlTemplate = configuration.getTemplate("Mapper.xml.ftl");
            Template serviceTemplate = configuration.getTemplate("Service.java.ftl");
            Template serviceImplTemplate = configuration.getTemplate("ServiceImpl.java.ftl");
            Template controllerTemplate = configuration.getTemplate("Controller.java.ftl");
            Template listenerTemplate = configuration.getTemplate("Listener.java.ftl");
            Template vueTemplate = configuration.getTemplate("Index.vue.ftl");
            Template vueApiTemplate = configuration.getTemplate("Api.js.ftl");
            for (TableEntity tableEntity : tableList) {
                String tableName = tableEntity.getTableName();
                List<ColumnEntity> columns = tableEntity.getColumns();
                if(CollUtil.isEmpty(columns)){
                    throw new BusinessException("列集合为空");
                }
                String path = generatorCodePath + "/" + tableEntity.getPackageName().replace(".", "/");
                generate(modelTemplate, tableEntity, path + "/domain/", tableEntity.getEntityName());
                generate(mapperJavaTemplate, tableEntity, path + "/mapper/", tableEntity.getMapperName());
                generate(mapperXmlTemplate, tableEntity, generatorCodePath + "/mapper/", tableEntity.getMapperName());
                generate(serviceTemplate, tableEntity, path + "/service/", tableEntity.getServiceName());
                generate(serviceImplTemplate, tableEntity, path + "/service/impl/", tableEntity.getServiceImplName());
                generate(controllerTemplate, tableEntity, path + "/controller/", tableEntity.getControllerName());
                generate(listenerTemplate, tableEntity, path + "/listener/", tableEntity.getListenerName());
                generate(vueTemplate, tableEntity, generatorCodePath + "/system/"+tableEntity.getModelName()+"/", "index");
                generate(vueApiTemplate, tableEntity, generatorCodePath + "/api/"+tableEntity.getModelName()+"/", "index");
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * @param template
     * @param tableClass
     * @param path
     * @param className
     * @throws Exception
     */
    private void generate(Template template, TableEntity tableClass, String path, String className) throws Exception {
        File folder = new File(path);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String fileName = path + className + template.getName().replace(".ftl", "")
                .replace("Controller", "")
                .replace("Service", "")
                .replace("ServiceImpl", "")
                .replace("Impl", "")
                .replace("Mapper", "")
                .replace("Entity", "")
                .replace("Listener", "")
                .replace("Api", "")
                .replace("Index", "");
        //log.info("className:{}",className);
        FileOutputStream fos = new FileOutputStream(fileName);
        OutputStreamWriter out = new OutputStreamWriter(fos);
        template.process(tableClass, out);
        fos.close();
        out.close();
    }
}
